home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / DEFPACKA.C < prev    next >
C/C++ Source or Header  |  1991-04-27  |  21KB  |  664 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *
  16.  * Edit history
  17.  * Created: LGO 30-Mar-89 -- Initial design and implementation.
  18.  *
  19.  * The DEFPACKAGE macro for Symbolic C++.
  20.  *
  21.  * Syntax:
  22.  *     DEFPACKAGE NAME <PATH> [OPTIONS] 
  23.  *
  24.  * Where NAME is a symbol prefix, PATH is the name of an include file where
  25.  * definitions are kept, and OPTIONS are optional, seprated by comma's and
  26.  * one of the following:
  27.  * 
  28.  * count=identifier
  29.  *     This says that the include file should include a #define identifier
  30.  *     whose expansion is the number of symbols defined.
  31.  * 
  32.  * use_first=int
  33.  *      When non-zero, the symbol value used is the first definition.
  34.  *      Redefinition attempts are ignored. (this is used by the ONCE-ONLY
  35.  *      macro)
  36.  *
  37.  * noblank=int
  38.  *      When non-zero, remove all whitespace from symbol names
  39.  *
  40.  * case=upper
  41.  *     This says to upcase all symbol names.
  42.  * case=lower
  43.  *     This says to downcase all symbol names.
  44.  * case=cap
  45.  *     This says to capitalize the first letter of each symbol name, and
  46.  *     downcase the rest.
  47.  * case=sensitive
  48.  *     This says to leave the case alone.  This is the default.
  49.  * 
  50.  * start=int
  51.  *     This says to start counting from int (default is zero).
  52.  * increment=int
  53.  *     This says to increment counting by int (default is one).
  54.  * template=int
  55.  *     This value is inclusive-or'ed with every symbol value.
  56.  * max=int
  57.  *     This says to generate an error when the number of symbol exceeds int.
  58.  *
  59.  * Symbols are inserted in a package with the following macro:
  60.  * 
  61.  *     DEFPACKAGE_SYMBOL(package, symbol, type, value, property, expander)
  62.  *
  63.  * where:
  64.  *   package     is the name of a package (the DEFPACKAGE must preceed)
  65.  *   symbol     is the name of the symbol
  66.  *   type    [optional] is the type of the value
  67.  *   value    [optional] is the value of the symbol or property
  68.  *   property    [optional] is the name of the property (empty means use the
  69.  *        value slot) 
  70.  *   expander=identifier
  71.  *         This says to replace the DEFPACKAGE_SYMBOL invocation
  72.  *        with the result of calling the "identifier" macro.
  73.  *
  74.  * The expander macro is called with the following arguments: 
  75.  *
  76.  *      expander(index, symbol, type, value)
  77.  *
  78.  * where:
  79.  *   expander   is the expander macro specified in the DEFPACKAGE_SYMBOL
  80.  *   index    is the symbol's index number
  81.  *   symbol     is the name of the symbol
  82.  *   type    is the type of the value [may be empty]
  83.  *   value    is the value of the symbol or property [may be empty]
  84.  *
  85.  * DEFPACKAGE_SYMBOL causes three macro definitions to be written to the
  86.  * package's definition file:
  87.  *
  88.  *   pkgname_DEFINITIONS - expands into macro calls to define the symbols
  89.  *   pkgname_VALUES     - expands into macro calls to set symbol values
  90.  *   pkgname_PROPERTIES     - expands into macro calls to set symbol properties
  91.  *
  92.  * where pkgname is the name of the package.  Each of these macros takes a
  93.  * single parameter which is the name of the function or macro to call for each
  94.  * symbol.
  95.  *
  96.  * Examples:
  97.  *   #define package##_DEFINITIONS(define_macro) \
  98.  *     define_macro(index, name)
  99.  *
  100.  *   #define package##_VALUES(value_macro) \
  101.  *      value_macro(index, name, type, value)
  102.  *
  103.  *   #define package##_PROPERTIES(property_macro) \
  104.  *    property_macro(index, name, property, type, value)
  105.  *
  106.  * where:
  107.  *  index    is the symbol index.
  108.  *  name    is the symbol name.
  109.  *  type    is the type of the value
  110.  *  value    is the value of the symbol
  111.  *  property    is a pointer to the properties symbol
  112.  *
  113.  * See package.h for examples.
  114.  *
  115.  * In order to define sym_names, the sym_db  file must be  included in a single
  116.  * .C file.  If  the makefile  has a  dependency between the   .C  file and the
  117.  * sym_db file, then the  .C file will be  re-compiled  whenever someone adds a
  118.  * new  symbol.   The .C  file which   includes  the sym_db  file can add other
  119.  * support for symbols,  such as  allocating static vectors indexed by symbols,
  120.  * defining hash tables, variable-length vectors and intern functions.
  121.  */  
  122.  
  123. /*
  124.  * This file exports the following functions:
  125.  * PACKAGE*
  126.  * package_define(char* name, char* filename, char* count,
  127.  *                char* scase, 
  128.  *                long start, long incr, long template, 
  129.  *                long max, long use_first);
  130.  *
  131.  * int
  132.  * define_symbol(argc, argv);
  133.  *
  134.  * void
  135.  * symbol_define(PACKAGE* pkg, char* name, char* type, 
  136.  *               char* value, char* property);
  137.  *
  138.  * void
  139.  * finish_symbols();
  140.  */
  141. #include "defmacio.h"
  142.  
  143. typedef enum {c_sensitive, c_upper, c_lower, c_cap} CASE;
  144.  
  145. typedef struct package {
  146.   struct package* next;        /* Next package in package_list */
  147.   char* name;            /* Package name */
  148.   char* filename;        /* Package definition file name */
  149.   FILE* file;            /* Package definition file */
  150.   struct Hash_Table* symbols;    /* Symbol table */
  151.   Boolean is_changed;        /* TRUE when file must be written */
  152.   long index;            /* Largest index in package */
  153.   long count;            /* Number of symbols in the package */
  154.   char* count_name;        /* Name of #define to hold symbol count */
  155.   CASE scase;            /* one of upper, lower, cap, sensitive */
  156.   char* case_name;        /* string version of scase */
  157.   long start;            /* Starting symbol index */
  158.   long incr;            /* symbol index increment */
  159.   long template;        /* symbol index template */
  160.   long max;            /* symbol index maximum */
  161.   Boolean use_first;        /* TRUE to ignore symbol value redefinitions */
  162.   Boolean nospace;        /* TRUE to remove whitespace from symbol names */
  163.   char* header;            /* Header at start of definition file */
  164. } PACKAGE;
  165.  
  166. static PACKAGE* package_list = NULL;
  167.  
  168. typedef struct property {
  169.   struct property* next;    /* Pointer to next value, or NULL */
  170.   char* property;        /* Property name string */
  171.   char* value;            /* Value string */
  172.   char* type;            /* Type of value */
  173. } PROPERTY;
  174.  
  175. typedef struct symbol {
  176.   char* name;            /* Symbol name */
  177.   long index;            /* Symbol index */
  178.   char* type;            /* Symbol type */
  179.   char* value;            /* Symbol value */
  180.   PROPERTY* props;        /* pointer to properties or NULL */
  181. } SYMBOL;
  182.  
  183. static SYMBOL*
  184. add_symbol(pkg, name, index)
  185.   PACKAGE* pkg;
  186.   char* name;
  187.   long index;
  188. {
  189.   SYMBOL* symbol = (SYMBOL*) getmem(sizeof(SYMBOL));
  190.   symbol->name = name;
  191.   symbol->index = index;
  192.   symbol->type = "";
  193.   symbol->value = "";
  194.   symbol->props = NULL;
  195.   put_hash(pkg->symbols, name, symbol);
  196.   if(index > pkg->index) pkg->index = index;
  197.   pkg->count++;
  198.   return symbol;
  199. }
  200.  
  201. static long next_index(pkg)
  202.  PACKAGE* pkg;
  203. {
  204.   long template = pkg->template;
  205.   long result = ((pkg->index & ~template) + pkg->incr);
  206.   if (pkg->max > 0 && result > pkg->max)
  207.     cerror ("DEFPACKAGE-SYMBOL: too many symbols in the %s package", pkg->name);
  208.   return result | template;
  209. }
  210.  
  211. /*
  212.  * Given a package object and the symbol name,
  213.  * intern the symbol in the package, and insert the
  214.  * symbol replacement into the input stream.
  215.  */
  216. SYMBOL*
  217. symbol_define(pkg, name, type, value, property)
  218.   PACKAGE* pkg;
  219.   char* name;
  220.   char* type;
  221.   char* value;
  222.   char* property;
  223. {
  224.   SYMBOL* symbol;
  225.   if (pkg->nospace)              /* Trim whitespace */
  226.     name = c_trim_all(name, " \t\n");
  227.                       /* Set symbol name case */
  228.   switch (pkg->scase) {
  229.   case c_upper: c_upcase(name);
  230.   case c_lower: c_downcase(name);
  231.   case c_cap: c_capitalize(name);
  232.   }                      /* Lookup symbol */
  233.   symbol = (SYMBOL*) get_hash(pkg->symbols, name);
  234.   if (symbol == NULL) {              /* Create new symbols */
  235.     symbol = add_symbol(pkg, name, pkg->index);
  236.     pkg->index = next_index(pkg);
  237.     pkg->is_changed = TRUE;
  238.   }
  239.   if (*value != EOS) {
  240.     if (*property == EOS) {          /* Set value */
  241.       if (!pkg->use_first || *symbol->value == EOS) {
  242.     if (!pkg->is_changed &&
  243.         (strcmp(symbol->type, type) != 0 ||
  244.          strcmp(symbol->value, value) != 0))
  245.       pkg->is_changed = TRUE;
  246.     symbol->type = type;
  247.     symbol->value = value;
  248.       }
  249.     } else {                  /* Set property */
  250.       PROPERTY* prop = symbol->props;
  251.       for (; prop != NULL; prop = prop->next)
  252.     if (!strcmp(prop->property, property)) break;
  253.       if(prop == NULL) {
  254.     prop = (PROPERTY*) getmem(sizeof(PROPERTY));
  255.     prop->property = property;
  256.     prop->next = symbol->props;
  257.     symbol->props = prop;
  258.     pkg->is_changed = TRUE;
  259.       }
  260.       if (!pkg->is_changed &&
  261.       (strcmp(prop->type, type) != 0 ||
  262.        strcmp(prop->value, value) != 0))
  263.     pkg->is_changed = TRUE;
  264.       prop->type = type;
  265.       prop->value = value;
  266.     }
  267.   }
  268.   return symbol;
  269. }
  270.  
  271. /* Read in the file which describes the symbols in package */
  272. /* The package file starts with the following:             */
  273.  
  274. static char* header =
  275. "/*\n\
  276.  * DEFPACKAGE %-20s definitions file.\n\
  277.  *\n\
  278.  * This file is automatically generated by the cpp DEFPACKAGE facility\n\
  279.  * DO NOT EDIT THIS FILE, because it may be re-writen the next time CPP\n\
  280.  * is run.\n\
  281.  *\n\
  282.  * This file is for:\n\
  283.  * DEFPACKAGE %s";
  284.  
  285. static char* header_warning = "\n/* WARNING: Do not remove this line */\n";
  286.  
  287. static Boolean
  288. token_scan(pkg, search, end)
  289.   PACKAGE* pkg;
  290.   char* search;
  291.   char end;
  292. {
  293.   FILE* stream = pkg->file;
  294.   int len = strlen(search);
  295.   int i;
  296.   for(i=0; i<len;) {
  297.     char c = fgetc(stream);
  298.     append_char(work_string, c);
  299.     if(c == search[i]) { i++; continue;}
  300.     if(c == EOF) return FALSE;
  301.     if(c == end) return FALSE;
  302.     if (i>0) {
  303.       i=0;
  304.       if(c == search[i]) { i++; continue;}
  305.     }
  306.   }
  307.   *(work_string->buffp) = EOS;
  308.   return TRUE;
  309. }
  310.  
  311. /*
  312.  * HACK ALERT
  313.  *   Read a line from stream, and put it in the input buffer used by getchar
  314.  *   This lets read_package use the scan_next utility in defmacio.c
  315.  */
  316. static void
  317. read_inline(stream)
  318.   FILE* stream;
  319. {
  320. #define INBUFLEN 200
  321.   static char instring[INBUFLEN];
  322.   fgets(instring, INBUFLEN, stream);
  323.   set_inbuffer(instring);
  324. }
  325.  
  326. static Boolean
  327. read_package (pkg)
  328.   PACKAGE* pkg;
  329. {
  330.   FILE* stream = pkg->file;
  331.   char token[400];
  332.   char error[100];
  333.   char* symname;
  334.   long symindex=-1;
  335.                       /* Check for empty file */
  336.   char c = fgetc(stream);
  337.   if (c == EOF) pkg->is_changed = TRUE;
  338.   else {
  339.                       /* Scan the header */
  340.     scan_start();
  341.     append_char(work_string, c);    
  342.     if(!token_scan(pkg, header_warning, EOF)) {
  343.       cerror ("defpackage: Can't find \"Do not remove\" comment in the %s file",
  344.           pkg->filename);
  345.       return FALSE;
  346.     }              /* Everything up to header_warning is header*/
  347.     pkg->header = savestring(work_string->buff);
  348.     /*
  349.      * MACRO package##_DEFINITIONS(define_macro, value_macro, property_macro) {
  350.      *     define_macro  (index, name)
  351.      *     value_macro   (index, type, value)
  352.      *     property_macro(index, property, type, value)
  353.      * }
  354.      */
  355.     if(!token_scan(pkg, "_DEFINITIONS", EOF)) {
  356.       cerror ("defpackage: Can't find pkg_DEFINITIONS in the %s file",
  357.           pkg->filename);
  358.       return FALSE;
  359.     }
  360.     token_scan(pkg, "\n", EOF);
  361.     for(;;) {
  362.       enum {Tdefine, Tvalue, Tproperty} type;
  363.       char* type_name;
  364.       char* value_name;
  365.       char* property_name;
  366.       long index;
  367.  
  368.       read_inline(stream);
  369.       c = skip_blanks();          /* Quit on close brace '}' */
  370.       if (c == '}') break;
  371.       unget();
  372.       copytoken(token);
  373.       if (strcmp(token, "define_macro") == 0) type = Tdefine;
  374.       else if (strcmp(token, "value_macro") == 0) type = Tvalue;
  375.       else if (strcmp(token, "property_macro") == 0) type = Tproperty;
  376.       else {
  377.     sprintf (error, "defpackage: unknown macro %s while reading %s",
  378.          token, pkg->filename);
  379.     cerror(error, "");
  380.     return FALSE;
  381.       }
  382.       if((c = skip_blanks()) != '(') {
  383.     sprintf(error, "defpackage: Found '%c' instead of '(' after %s in %s",
  384.         c, token, pkg->filename);
  385.     cerror(error, "");
  386.     return FALSE;
  387.       }
  388.       copytoken(error);
  389.       index = strtol(error, &value_name, 10);
  390.       if (*value_name != '\0') {
  391.     sprintf (error, "defpackage: bad symbol number in %s while reading %s",
  392.          token, pkg->filename);
  393.     cerror(error, "");
  394.     return FALSE;
  395.       }
  396.       skip_blanks();              /* Skip comma */
  397.       property_name = "";
  398.       switch (type) {
  399.       case Tdefine:
  400.     symname = scan_token(",)");
  401.     symindex = index;
  402.     add_symbol(pkg, symname, index);
  403.     break;
  404.       case Tproperty:
  405.     property_name = scan_token(",)"); /* Get property */
  406.     /* fall through */
  407.       case Tvalue:
  408.     getchar();              /* Skip comma */
  409.     type_name = scan_token(",)");      /* Get type */
  410.     getchar();              /* Skip comma */
  411.     value_name = scan_token(",)");      /* Get value */
  412.     if (index != symindex) {
  413.       sprintf(error, "defpackage: macros out of order reading %s(%d...) in %s",
  414.          token, index, pkg->filename);
  415.       cerror(error, "");
  416.       return FALSE;
  417.     }
  418.     symbol_define(pkg, symname, type_name, value_name, property_name);
  419.     break;
  420.       }
  421.       if((c = skip_blanks()) != ')') {
  422.     sprintf(error, "defpackage: '%c' instead of ')' while reading %s(%d...) in %s",
  423.            c, token, index, pkg->filename);
  424.     cwarn(error, "");
  425.       }
  426.     }
  427.   }
  428.   return TRUE;
  429. }
  430.  
  431. static void write_package (pkg)
  432.   PACKAGE* pkg;
  433. {
  434.   SYMBOL* symbol;
  435.   char* name = pkg->name;
  436.   FILE* stream = pkg->file;          /* Header */
  437.   SYMBOL** symtab = (SYMBOL**) getmem(sizeof(SYMBOL*)*pkg->count);
  438.   int i;
  439.   if (pkg->header != NULL)          /* If a header read in */
  440.     fprintf(stream, pkg->header);      /* use it */
  441.   else {                  /* else use the default header */
  442.     fprintf (stream, header, name, name);
  443.                       /* defpackage options */
  444.     fprintf (stream, " <%s> name=%s,\n",
  445.          pkg->name, pkg->filename, pkg->count_name);
  446.     fprintf (stream, " *\t count=%s, case=%s,\n",
  447.          pkg->count_name, pkg->case_name);
  448.     fprintf (stream, " *\t start=%d, increment=%d, template=%d, max=%d\n",
  449.          pkg->start, pkg->incr, pkg->template, pkg->max);
  450.     fprintf (stream, " */\n\n");
  451.     fprintf (stream, "%s", header_warning);
  452.   }
  453.                       /* COUNT #define */
  454.   if(*pkg->count_name)
  455.     fprintf (stream, "#define %s %d\n\n", pkg->count_name, pkg->count);
  456.   /*
  457.    * MACRO package##_DEFINITIONS(define_macro, value_macro, property_macro) {
  458.    *     define_macro  (index, name)
  459.    *     value_macro   (index, type, value)
  460.    *     property_macro(index, property, type, value)
  461.    * }
  462.    */
  463.   fprintf (stream, "MACRO %s_DEFINITIONS", name);
  464.   fprintf (stream, "(define_macro, value_macro, property_macro) {");
  465.   for(i=0; i < pkg->count; i++) symtab[i] = NULL;
  466.   symbol = (SYMBOL*) next_hash(pkg->symbols, TRUE);
  467.   for(i=0; symbol != NULL; i++) {      /* Sort symbols by index */
  468.     if(symbol->index >= pkg->count) {
  469.       char error[100];
  470.       sprintf(error, "Symbol %s has a bad index %ld, ignored",
  471.           symbol->name, symbol->index);
  472.       cerror(error, "");
  473.     }
  474.     else
  475.       symtab[symbol->index] = symbol;
  476.     symbol = (SYMBOL*) next_hash(pkg->symbols, FALSE);
  477.   }
  478.   for(i=0; i < pkg->count; i++) {
  479.     symbol = symtab[i];
  480.     if (symbol != NULL) {
  481.       PROPERTY* prop = symbol->props;
  482.       fprintf (stream, "\n  define_macro  (%ld, %s)",
  483.            symbol->index, symbol->name);
  484.       if(*symbol->value)
  485.     fprintf (stream, "\n  value_macro   (%ld, %s, %s)",
  486.          symbol->index,
  487.          (*symbol->type) ? symbol->type : "void*",
  488.          (*symbol->value) ? symbol->value : "0");
  489.       while(prop) {
  490.     fprintf (stream, "\n  property_macro(%ld, %s, %s, %s)",
  491.          symbol->index, prop->property,
  492.          (*prop->type) ? prop->type : "void*",
  493.          (*prop->value) ? prop->value : "0");
  494.     prop = prop->next;
  495.       }
  496.     }
  497. #ifdef paranioa
  498.     else
  499.       fprintf (stderr, "Warning: Missing symbol %d from package %s\n",
  500.            i, name);
  501. #endif
  502.   }
  503.   fprintf (stream, "\n}\n");
  504. }
  505.  
  506. void
  507. package_define(name, filename, count_name, case_name,
  508.            start, incr, template, max, use_first, nospace)
  509.   char* name;
  510.   char* filename;
  511.   char* count_name;
  512.   char* case_name;
  513.   long start;
  514.   long incr;
  515.   long template;
  516.   long max;
  517.   long use_first;
  518.   long nospace;
  519. {
  520.   PACKAGE* pkg;                /* check for package already defined */
  521.   for(pkg = package_list; pkg != NULL; pkg=pkg->next)
  522.     if (strcmp(pkg->name, name) == 0) {
  523.       cerror("DEFPACKAGE: redefining the %s package", name);
  524.       return;
  525.     }
  526.   pkg = (PACKAGE*) getmem(sizeof (PACKAGE));
  527.   if ((pkg->file = fopen (filename, "r+")) == NULL) {/* If we can't open the file */
  528.     cerror ("defpackage: cannot open %s for update", filename);
  529.     return;
  530.   }
  531.   pkg->next = package_list;    /* Link new package on package list */
  532.   package_list = pkg;
  533.   pkg->is_changed = FALSE;
  534.   pkg->symbols = init_Hash_Table();
  535.   pkg->name = name;
  536.   pkg->filename = filename;
  537.   pkg->count = 0;
  538.   pkg->count_name = count_name;
  539.   pkg->start = start;
  540.   pkg->index = start;
  541.   pkg->incr = (incr>0) ? incr : 1;
  542.   pkg->template = template;
  543.   pkg->max = max;
  544.   pkg->use_first = (use_first != 0);
  545.   pkg->nospace = (nospace != 0);
  546.   pkg->scase = c_sensitive;
  547.   pkg->case_name = "sensitive";
  548.   if (*case_name != EOS) {
  549.     pkg->case_name = case_name;
  550.     c_downcase(case_name);
  551.     if (strcmp(case_name, "sensitive") == 0)
  552.       pkg->scase = c_sensitive;
  553.     else if (strcmp(case_name, "upper") == 0)
  554.       pkg->scase = c_upper;
  555.     else if (strcmp(case_name, "lower") == 0)
  556.       pkg->scase = c_lower;
  557.     else if (strcmp(case_name, "cap") == 0)
  558.       pkg->scase = c_cap;
  559.     else
  560.       cerror ("defpackage: Illegal case: %s", case_name);
  561.   }
  562.   pkg->header = NULL;
  563.   read_package(pkg);    /* Read package from file */
  564.   if (pkg->count > 0) {
  565.     pkg->is_changed = FALSE;
  566.     pkg->index = next_index(pkg); /* setup the next index */
  567.   }
  568. }
  569.  
  570. /*
  571.  * Given a symbol name in a package, return its value string
  572.  */
  573. char* lookup_symbol(pkgname, symname)
  574.   char* pkgname;
  575.   char* symname;
  576. {
  577.   char* value = NULL;
  578.   static char* pkgname_cache = NULL;
  579.   static PACKAGE* package = NULL;
  580.  
  581.   if (pkgname != pkgname_cache) {
  582.     pkgname_cache = pkgname;
  583.                       /* Lookup package */
  584.     for(package=package_list; package!=NULL; package=package->next)
  585.       if(!strcmp(package->name, pkgname)) break;
  586.   }
  587.   if (package != NULL) {
  588.     SYMBOL* symbol = (SYMBOL*) get_hash(package->symbols, symname);
  589.     if (symbol != NULL)
  590.       value = symbol->value;
  591.   }
  592.   return value;
  593. }
  594.  
  595. /*
  596.  * DEFPACKAGE_SYMBOL(package, symbol, type, value, property, expander)
  597.  */
  598. int
  599. define_symbol(argc, argv)
  600.      int argc;
  601.      char* argv[];
  602. {
  603.   char* parms[6];
  604.   int i;
  605.   PACKAGE* pkg;
  606.   while(getchar() != '(') ;          /* Skip over macro name */
  607.   for(i=0; i<6; i++) parms[i] = "";      /* Initialize parms */
  608.   for(i=0; i<6; i++) {
  609.     parms[i] = scan_token(",)");
  610.     if (getchar() == ')') break;      /* Quit on ) */
  611.   }
  612.                       /* Lookup package */
  613.   for(pkg=package_list; pkg!=NULL; pkg=pkg->next)
  614.     if(!strcmp(pkg->name, parms[0])) break;
  615.   if(pkg == NULL) {
  616.     cerror("DEFPACKAGE_SYMBOL: undefined package name: %s", parms[0]);
  617.     return 1;
  618.   } else {
  619.     char result[100];
  620.     SYMBOL* symbol = 
  621.       symbol_define(pkg, parms[1], parms[2], parms[3], parms[4]);
  622.     /*
  623.      * insert replacement string
  624.      *    expander(index, symbol, type, value)
  625.      */
  626.     char* expander = parms[5];
  627.     if (*expander != EOS) {
  628.       sprintf(result, "%s(%d, ", expander, symbol->index);
  629.       puts(result);
  630.       put_string(symbol->name);
  631.       sprintf(result, ", %s, %s)",
  632.           (*symbol->type) ? symbol->type : "void*",
  633.           (*symbol->value) ? symbol->value : "0");
  634.       puts(result);
  635.     }
  636.   }
  637.   return 0;
  638. }
  639.  
  640. /*
  641.  * Called just before cpp terminates
  642.  * We write out the new header file here (when necessary)
  643.  */
  644. static void
  645. finalize_package(pkg)
  646.   struct package* pkg;
  647. {
  648.   if(pkg->is_changed) {        /* If package was updated/changed */
  649.  /*   fprintf(stderr, "Writing %s\n", pkg->filename);  *********** DEBUG ********* */
  650.     rewind(pkg->file);
  651.     write_package(pkg);        /* Write new header file */
  652.   }
  653.   close(pkg->file);
  654. }
  655.  
  656. /*
  657.  * This is called at the end of CPP to close and/or re-write package header files
  658.  */
  659. finish_symbols() {
  660.   PACKAGE* pkg = package_list;
  661.   for (; pkg != NULL; pkg = pkg->next)
  662.     finalize_package(pkg);
  663. }
  664.